package com.magnusart.scrumify.dao;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.Collections;
import java.util.List;

import org.junit.Test;

import com.magnusart.scrumify.dao.CommonDAO;
import com.magnusart.scrumppm.model.Builder;

public abstract class GenericDAOSpecification<J extends Comparable<? super J>, X extends Comparable<? super X>, Y extends Builder, T extends CommonDAO<J, X, Y> >
{
	T dao;
	X entry1;
	X entry2;
	X entry3;
	Y builder;
	J parent;

	@Test
	public void deleteAddedEntry( ) throws Exception {
		System.out.println("Adding 2 entries.");
		X a1 = dao.add( parent, entry1 );
		X a2 = dao.add( parent, entry2 );
		
		assertFalse( a1 == null );
		assertFalse( a2 == null );
		
		System.out.println("deleteAddedEntry: Retrieving all entries.");
		List<X> entries = dao.getAll( parent );
	
		// Make sure they are in the list.
		int index = Collections.binarySearch( entries, a1 );
		assertTrue( index >= 0 );
		index = Collections.binarySearch( entries, a2 );
		assertTrue( index >= 0 );
		
		System.out.println("deleteAddedEntry: Deleting one entry.");
		// Delete the entry
		X deleted = dao.delete( entry2 );
		
		assertTrue( deleted != null );
		
		System.out.println("deleteAddedEntry: Retrieving one entry.");
		X isDeleted = dao.getOne( deleted );
		
		assertTrue( isDeleted == null );
	}
	
	@Test
	public void insertedEntryShouldReturnTheSame() throws Exception {
		System.out.println("insertReturnSame: Adding one entry.");
		X a1 = dao.add( parent, entry1 );
		assertTrue( "The entries should be identical.", compareWithoutID( a1, entry1 ) );
	}
	
	abstract boolean compareWithoutID( X a, X c );

	@Test
	public void entriesShouldBeUpdateable() throws Exception {
		assertFalse( parent == null && entry3 == null && builder == null );
		
		System.out.println("entriesSame: adding one entry.");
		X a1 = dao.add( parent, entry3 );
		assertFalse( a1 == null );
		
		System.out.println("entriesSame: retrieving one entry.");
		X a2 = dao.getOne( entry3 );
		assertFalse( a2 == null );
		
		System.out.println("entriesSame: updating one entry.");
		X a3 = dao.update( parent, a2, builder );
		assertFalse( a3 == null );
		assertTrue( deepEquality( a3, builder ) );
		System.out.println("\n\n===========\n\n");
	}
	
	abstract boolean deepEquality( X a, Y b );
}
